////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __WN_ASSERT_H__
#define __WN_ASSERT_H__

#include "WNCore/inc/WNBase.h"
#include "WNCore/inc/WNDefines.h"

__WN_INLINE WN_VOID WNAssert(WN_INT32 _argument, const WN_CHAR* _file, WN_UINT32 _line, const WN_CHAR* _message);

#define WN_RELEASE_ASSERT_DESC(_argument, _description) WNAssert((WN_INT32)(_argument), __FILE__, __LINE__, _description)
#define WN_RELEASE_ASSERT(_argument) WN_RELEASE_ASSERT_DESC(_argument, WN_STRINGERIZE(_argument))

#ifdef _WN_DEBUG
    #define WN_DEBUG_ASSERT_DESC(_argument, _description) WNAssert((WN_INT32)(_argument), __FILE__, __LINE__, _description)
#else
    #define WN_DEBUG_ASSERT_DESC(_argument, _description)
#endif

#define WN_DEBUG_ASSERT(_argument) WN_DEBUG_ASSERT_DESC(_argument, WN_STRINGERIZE(_argument))

#ifdef _WN_HAS_NATIVE_STATIC_ASSERT
    #define WN_STATIC_ASSERT_DESC(_argument, _description) static_assert(_argument, _description)

    #undef _WN_HAS_NATIVE_STATIC_ASSERT
#else
    #ifdef _WN_CPLUSPLUS
        template <WN_BOOL b>
        struct __WNStaticAssert{};

        template <>
        struct __WNStaticAssert<WN_TRUE> {
            static WN_VOID IsValid() {};
        };

        #define WN_STATIC_ASSERT_DESC(_argument, _description) __WNStaticAssert<_argument>::IsValid()
    #else
        #define WN_STATIC_ASSERT_DESC(_argument, _description) typedef char STATIC_ASSERT_##__LINE__[(!!(_argument)) * 2 - 1]
    #endif
#endif

#define WN_STATIC_ASSERT(_argument) WN_STATIC_ASSERT_DESC(_argument, WN_STRINGERIZE(_argument))

#include "WNCore/inc/WNAssert.inl"

#endif // __WN_ASSERT_H__
